import { Button, Col, Input, Row, Form, message } from 'antd'
import React, { useState, useCallback, useEffect } from 'react'
import omit from 'omit.js'
import { FormItemProps } from 'antd/es/form/FormItem'
import { HttpGetSmsCode } from '@/services/login'

import ItemMap from './map'
import LoginContext, { LoginContextProps } from './LoginContext'
import styles from './index.less'

export type WrappedLoginItemProps = LoginItemProps
export type LoginItemKeyType = keyof typeof ItemMap
export interface LoginItemType {
    Username: React.FC<WrappedLoginItemProps>
    Password: React.FC<WrappedLoginItemProps>
    Mobile: React.FC<WrappedLoginItemProps>
    Captcha: React.FC<WrappedLoginItemProps>
}

export interface LoginItemProps extends Partial<FormItemProps> {
    name?: string
    style?: React.CSSProperties
    placeholder?: string
    buttonText?: React.ReactNode
    countDown?: number
    getCaptchaButtonText?: string
    getCaptchaSecondText?: string
    updateActive?: LoginContextProps['updateActive']
    type?: string
    defaultValue?: string
    customProps?: { [key: string]: unknown }
    onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
    tabUtil?: LoginContextProps['tabUtil']
}

const FormItem = Form.Item

const getFormItemOptions = ({ onChange, defaultValue, customProps = {}, rules }: LoginItemProps) => {
    const options: {
        rules?: LoginItemProps['rules']
        onChange?: LoginItemProps['onChange']
        initialValue?: LoginItemProps['defaultValue']
    } = {
        rules: rules || (customProps.rules as LoginItemProps['rules']),
    }
    if (onChange) {
        options.onChange = onChange
    }
    if (defaultValue) {
        options.initialValue = defaultValue
    }
    return options
}

const LoginItem: React.FC<LoginItemProps> = (props) => {
    const [count, setCount] = useState<number>(props.countDown || 0)
    const [timing, setTiming] = useState(false)
    const {
        onChange,
        customProps,
        defaultValue,
        rules,
        name,
        getCaptchaButtonText,
        getCaptchaSecondText,
        updateActive,
        type,
        tabUtil,
        ...restProps
    } = props

    const onGetCaptcha = useCallback(async (phone: string) => {
        const { flag } = await HttpGetSmsCode({ phone })
        if (flag !== 1) {
            return
        }
        message.success('获取验证码成功！')
        setTiming(true)
    }, [])

    useEffect(() => {
        let interval: number = 0
        const { countDown } = props
        if (timing) {
            interval = window.setInterval(() => {
                setCount((preSecond) => {
                    if (preSecond <= 1) {
                        setTiming(false)
                        clearInterval(interval)
                        // 重置秒数
                        return countDown || 60
                    }
                    return preSecond - 1
                })
            }, 1000)
        }
        return () => clearInterval(interval)
    }, [timing])

    if (!name) {
        return null
    }

    const options = getFormItemOptions(props)
    const otherProps = restProps || {}

    if (type === 'Captcha') {
        const inputProps = omit(otherProps, ['onGetCaptcha', 'countDown'] as any)
        return (
            <FormItem shouldUpdate noStyle>
                {({ getFieldValue }) => (
                    <Row gutter={8}>
                        <Col span={16}>
                            <FormItem name={name} {...options}>
                                <Input {...customProps} {...inputProps} />
                            </FormItem>
                        </Col>
                        <Col span={8}>
                            <Button
                                disabled={timing}
                                className={styles.getCaptcha}
                                size='large'
                                onClick={async () => {
                                    const value = getFieldValue('phone')
                                    await onGetCaptcha(value)
                                }}>
                                {timing ? `${count} 秒` : '获取验证码'}
                            </Button>
                        </Col>
                    </Row>
                )}
            </FormItem>
        )
    }
    return (
        <FormItem name={name} {...options}>
            <Input {...customProps} {...otherProps} />
        </FormItem>
    )
}

const LoginItems: any = {}

Object.keys(ItemMap).forEach((key) => {
    const item = ItemMap[key]
    LoginItems[key] = (props: LoginItemProps) => (
        <LoginContext.Consumer>
            {(context) => (
                <LoginItem
                    customProps={item.props}
                    rules={item.rules}
                    {...props}
                    type={key}
                    {...context}
                    updateActive={context.updateActive}
                />
            )}
        </LoginContext.Consumer>
    )
})

export default LoginItems as LoginItemType
